﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using JsonEditor.Common;
using JsonEditor.Extensions;
using JsonEditor.Models;
using JsonEditor.Utils;
using Newtonsoft.Json.Linq;

namespace JsonEditor
{
    public partial class JsonForm : Form
    {
        JsonSetting _jsonSetting = null;

        string path
        {
            get
            {
                return Path.Combine(Application.StartupPath, "81206.json");
            }
        }
        public JsonForm()
        {
            InitializeComponent();
            _jsonSetting = new JsonSetting();
            propertyGrid1.SelectedObject = _jsonSetting;
        }

        private void JsonForm_Load(object sender, EventArgs e)
        {
            StreamReader reader = new StreamReader(path);
            string json = reader.ReadToEnd();
            reader.Close();
            JObject obj = JObject.Parse(json);

            TreeNode tn = new TreeNode
            {
                Name = "",
                Tag = "Root",
                Text = "Root"
            };
            tn.Tag = tn.ToJsonNode();
            treeView1.Nodes.Add(tn);
            TreeNode mainNode = treeView1.Nodes[0];
            getAllProperties(obj, mainNode);
            treeView1.ExpandAll();

            CProperty myProp = new CProperty("Test", "test2");
            myProp.Converter = new ListConverter(new string[] { "test1", "test2", "test3" });

            #region
            //CProperty myProp1 = new CProperty("Test1", "test");

            //propertyGrid1.Category = "test";

            //CProperty myProp2 = new CProperty("Test2", 1);

            //myProp2.Editor = new System.Drawing.Design.ColorEditor();

            //propertyGrid1.Add(myProp1);

            //myProperties.Add(myProp2);

            //grid.SelectedObject = myProperties;
            #endregion
        }

        void getAllProperties(JToken children, TreeNode mainNode)
        {
            foreach (JToken child in children.Children())
            {
                var property = child as JProperty;
                if (property == null)
                    continue;
                if (property.Value.Type == JTokenType.String)
                {
                    var text = string.Format("{0}: \"{1}\"", property.Name, property.Value.ToString());
                    TreeNode tn = new TreeNode
                    {
                        Name = property.Name,
                        Tag = property.Value.ToString(),
                        Text = text
                    };
                    tn.Tag = tn.ToJsonNode();
                    mainNode.Nodes.Add(tn);
                }
                if (property.Value.Type == JTokenType.Integer || property.Value.Type == JTokenType.Float)
                {
                    var text = string.Format("{0}: {1}", property.Name, property.Value);
                    object obj = property.Value;
                    if (property.Value.Type == JTokenType.Integer)
                    {
                        obj = property.Value.ToObject<int>();
                    }
                    else
                    {
                        obj = property.Value.ToObject<float>();
                    }
                    TreeNode tn = new TreeNode
                    {
                        Name = property.Name,
                        Tag = obj,
                        Text = text
                    };
                    tn.Tag = tn.ToJsonNode();
                    mainNode.Nodes.Add(tn);
                }
                if (property.Value.Type == JTokenType.Array)
                {
                    StringBuilder sb = new StringBuilder();
                    JArray array = (JArray)property.Value;
                    sb.AppendFormat("{0}: [", property.Name);
                    for (int i = 0; i < array.Count; i++)
                    {
                        if (JToken.FromObject(array[i]).Type == JTokenType.Float || JToken.FromObject(array[i]).Type == JTokenType.Integer)
                        {
                            sb.AppendFormat("{0}, ", array[i].ToString());
                        }
                        else
                        {
                            sb.AppendFormat("\"{0}\", ", array[i].ToString());
                        }
                    }
                    var text = sb.ToString().Trim().Trim(',') + "]";
                    TreeNode tn = new TreeNode
                    {
                        Name = property.Name,
                        Text = text
                    };
                    switch (JToken.FromObject(array[0]).Type)
                    {
                        case JTokenType.Integer:
                            List<int> lstInt = new List<int>();
                            for (int i = 0; i < array.Count; i++)
                            {
                                lstInt.Add(array[i].ToObject<int>());
                            }
                            tn.Tag = lstInt;
                            tn.Tag = AppUtils.ToJsonNode<List<int>>(tn);
                            break;
                        case JTokenType.Float:
                            List<float> lstFloat = new List<float>();
                            for (int i = 0; i < array.Count; i++)
                            {
                                lstFloat.Add(array[i].ToObject<float>());
                            }
                            tn.Tag = lstFloat;
                            tn.Tag = AppUtils.ToJsonNode<List<float>>(tn);
                            break;
                        case JTokenType.String:
                            List<string> lstString = new List<string>();
                            for (int i = 0; i < array.Count; i++)
                            {
                                lstString.Add(array[i].ToObject<string>());
                            }
                            tn.Tag = lstString;
                            tn.Tag = AppUtils.ToJsonNode<List<string>>(tn);
                            break;
                    }
                    mainNode.Nodes.Add(tn);
                }
                if (property.Value.Type == JTokenType.Object)
                {
                    var text = string.Format("{0}", property.Name);
                    TreeNode tn = new TreeNode
                    {
                        Name = property.Name,
                        Tag = property.Value.ToString(),
                        Text = text
                    };
                    tn.Tag = tn.ToJsonNode();
                    mainNode.Nodes.Add(tn);
                    getAllProperties(property.Value, mainNode.Nodes[tn.Name]);
                }
                // Console.WriteLine(property.Name +":" + property.Value);//print all of the values
                getAllProperties(child, mainNode);
            }
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Tag == null)
                return;
            propertyGrid1.SelectedObject = e.Node.Tag;
            //propertyGrid1.ExpandAllGridItems();
        }

        private void propertyGrid1_Paint(object sender, PaintEventArgs e)
        {
            var categorysinfo = propertyGrid1.SelectedObject.GetType().GetField("categorys", BindingFlags.NonPublic | BindingFlags.Instance);
            if (categorysinfo != null)
            {
                var categorys = categorysinfo.GetValue(propertyGrid1.SelectedObject) as List<String>;
                propertyGrid1.CollapseAllGridItems();
                GridItemCollection currentPropEntries = typeof(PropertyGrid).GetField("currentPropEntries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(propertyGrid1) as GridItemCollection;
                var newarray = currentPropEntries.Cast<GridItem>().OrderBy((t) => categorys.IndexOf(t.Label)).ToArray();
                currentPropEntries.GetType().GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(currentPropEntries, newarray);
                propertyGrid1.ExpandAllGridItems();
                object obj = propertyGrid1.Tag;
                if (obj != null)
                    propertyGrid1.PropertySort = (PropertySort)obj;
            }
            propertyGrid1.Paint -= new PaintEventHandler(propertyGrid1_Paint);
            //propertyGrid1.CollapseAllGridItems();
        }

        private void 保存SToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {

        }
    }
}
